package com.sky.service.impl;

import com.sky.constant.MessageConstant;
import com.sky.dto.GoodsSalesDTO;
import com.sky.entity.*;
import com.sky.exception.OrderBusinessException;
import com.sky.mapper.OrderDetailMapper;
import com.sky.mapper.OrderMapper;
import com.sky.mapper.UserMapper;
import com.sky.service.ReportService;
import com.sky.service.WorkSpaceService;
import com.sky.vo.*;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
public class ReportServiceImpl implements ReportService {

    @Autowired
    OrderMapper orderMapper;

    @Autowired
    UserMapper userMapper;

    @Autowired
    OrderDetailMapper orderDetailMapper;

    @Autowired
    private WorkSpaceService workSpaceService;

    /**
     * 营业额统计
     *
     * @param begin
     * @param end
     */
    @Override
    public TurnoverReportVO turnoverStatistics(LocalDate begin, LocalDate end) {
        //  获取日期列表
        String dateList = getDateList(begin, end);
        if (dateList == null) {
            throw new OrderBusinessException(MessageConstant.DATE_NOT_VALID);
        }

        //  获取营业额数据
        String turnoverList = getTurnoverList(begin, end);

        return TurnoverReportVO.builder()
                .dateList(dateList)
                .turnoverList(turnoverList).build();
    }


    /**
     * 用户统计
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public UserReportVO userStatistics(LocalDate begin, LocalDate end) {
        //  获取日期列表
        String dateList = getDateList(begin, end);

        if (dateList == null) {
            throw new OrderBusinessException(MessageConstant.DATE_NOT_VALID);
        }

        // 获取用户数据
        List<String> userList = getTotalUserList(begin, end);
        if (userList.size() != 2) {
            throw new OrderBusinessException(MessageConstant.UNKNOWN_ERROR);
        }

        //下标0对应总用户数  下标1对应新用户数
        return UserReportVO.builder()
                .dateList(dateList)
                .totalUserList(userList.get(0))
                .newUserList(userList.get(1)).build();
    }


    /**
     * 订单统计
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public OrderReportVO ordersStatistics(LocalDate begin, LocalDate end) {
        // 获取日期列表
        String dateList = getDateList(begin, end);
        if (dateList == null) {
            throw new OrderBusinessException(MessageConstant.UNKNOWN_ERROR);
        }

        // 获取订单数据
        List<OrderStatistic> totalOrderList = orderMapper.getOrderListByDateAndStatus(begin, end.plusDays(1), null);
        List<OrderStatistic> validOrderList = orderMapper.getOrderListByDateAndStatus(begin, end.plusDays(1), Orders.COMPLETED);

        // 将数据封装到map中
        Map<LocalDate, Long> totalMap = totalOrderList.stream()
                .collect(Collectors.toMap(OrderStatistic::getDay, OrderStatistic::getAmount));
        Map<LocalDate, Long> validMap = validOrderList.stream()
                .collect(Collectors.toMap(OrderStatistic::getDay, OrderStatistic::getAmount));

        //  构建数据
        StringBuilder orderCountList = new StringBuilder();
        StringBuilder validOrderCountList = new StringBuilder();

        int totalOrderCount = 0;
        int validOrderCount = 0;

        // 循环日期
        LocalDate currentDate = begin;
        while (!currentDate.isAfter(end)) {
            Long total = totalMap.getOrDefault(currentDate, 0L);
            Long valid = validMap.getOrDefault(currentDate, 0L);
            orderCountList.append(total);
            validOrderCountList.append(valid);
            totalOrderCount += total.intValue();
            validOrderCount += valid.intValue();
            if (!currentDate.equals(end)) {
                orderCountList.append(",");
                validOrderCountList.append(",");
            }
            currentDate = currentDate.plusDays(1);
        }

        // 计算订单完成率
        Double orderCompletionRate = totalOrderCount != 0 ? (double) validOrderCount / (double) totalOrderCount : 0.0;

        return OrderReportVO.builder()
                .dateList(dateList)
                .orderCountList(orderCountList.toString())
                .validOrderCountList(validOrderCountList.toString())
                .totalOrderCount(totalOrderCount)
                .validOrderCount(validOrderCount)
                .orderCompletionRate(orderCompletionRate).build();
    }


    /**
     * 销量排名
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public SalesTop10ReportVO top10(LocalDate begin, LocalDate end) {
        if (begin == null || end == null || end.isBefore(begin)) {
            throw new OrderBusinessException(MessageConstant.DATE_NOT_VALID);
        }

        List<GoodsSalesDTO> salesTop10List = orderDetailMapper.getTop10Sales(begin, end.plusDays(1));
        StringBuilder nameList = new StringBuilder();
        StringBuilder numberList = new StringBuilder();

        for (int i = 0; i < 10; i++) {
            GoodsSalesDTO sales = new GoodsSalesDTO();
            if (i < salesTop10List.size()) {
                sales = salesTop10List.get(i);
            }
            if (sales.getName() != null) {
                nameList.append(sales.getName());
                numberList.append(sales.getTotal());
            } else {
                nameList.append("暂无");
                numberList.append("0");
            }
            if (i != 9) {
                nameList.append(",");
                numberList.append(",");
            }
        }

        return SalesTop10ReportVO.builder()
                .nameList(nameList.toString())
                .numberList(numberList.toString()).build();
    }


    /**
     * 数据导出
     *
     * @param httpServletResponse
     */
    @Override
    public void export(HttpServletResponse httpServletResponse) {
        LocalDate beginDate = LocalDate.now().minusDays(30);
        LocalDate endDate = LocalDate.now();
        // 获取营业数据
        BusinessDataVO businessData = workSpaceService.businessData(beginDate, endDate);

        //通过POI将数据写入到Excel中
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("template/business_data_template.xlsx");
        try {

            if (in == null) {
                throw new RuntimeException("Excel模板文件未找到，请检查路径是否正确");
            }

            XSSFWorkbook excel = new XSSFWorkbook(in);

            //填充数据
            XSSFSheet sheet = excel.getSheet("Sheet1");
            //时间
            sheet.getRow(1).getCell(1).setCellValue("时间：" + beginDate + "————" + endDate.minusDays(1));

            //营业情况
            sheet.getRow(3).getCell(2).setCellValue(businessData.getTurnover()); //营业额
            sheet.getRow(3).getCell(4).setCellValue(businessData.getOrderCompletionRate()); //订单完成率
            sheet.getRow(3).getCell(6).setCellValue(businessData.getNewUsers()); //新增用户数
            sheet.getRow(4).getCell(2).setCellValue(businessData.getValidOrderCount()); //有效订单数
            sheet.getRow(4).getCell(4).setCellValue(businessData.getUnitPrice()); //平均每人消费

            //明细数据 30天
            for (int i = 0; i < 30; i++) {
                //获取日期
                LocalDate begin = beginDate.plusDays(i);
                LocalDate end = begin.plusDays(1);
                //获取营业数据
                BusinessDataVO businessDataVO = workSpaceService.businessData(begin, end);
                //设置到Excel中
                sheet.getRow(7+i).getCell(1).setCellValue(String.valueOf(begin)); //日期
                sheet.getRow(7+i).getCell(2).setCellValue(businessDataVO.getTurnover()); //营业额
                sheet.getRow(7+i).getCell(3).setCellValue(businessDataVO.getValidOrderCount()); //有效订单数
                sheet.getRow(7+i).getCell(4).setCellValue(businessDataVO.getOrderCompletionRate());//订单完成率
                sheet.getRow(7+i).getCell(5).setCellValue(businessDataVO.getUnitPrice()); //平均个人消费
                sheet.getRow(7+i).getCell(6).setCellValue(businessDataVO.getNewUsers());//新增用户数
            }

            ServletOutputStream out = httpServletResponse.getOutputStream();
            excel.write(out);

            //关闭资源
            out.close();
            excel.close();
            in.close();

        } catch (IOException e) {
            e.printStackTrace();
        }

    }


    /**
     * 获取用户数据
     *
     * @param begin
     * @param end
     * @return
     */
    private List<String> getTotalUserList(LocalDate begin, LocalDate end) {
        List<UserStatistic> userList = userMapper.getUserListByDate(begin, end.plusDays(1));

        Map<LocalDate, Long> map = userList.stream()
                .collect(Collectors.toMap(UserStatistic::getDay, UserStatistic::getAmount));

        StringBuilder totalUserList = new StringBuilder();
        StringBuilder newUserList = new StringBuilder();
        LocalDate currentDate = begin;
        Long sum = userMapper.getTotalUserBeforeDate(begin);
        while (!currentDate.isAfter(end)) {
            Long currentUser = map.getOrDefault(currentDate, 0L);
            newUserList.append(currentUser);
            sum += currentUser;
            totalUserList.append(sum);
            if (!currentDate.equals(end)) {
                newUserList.append(",");
                totalUserList.append(",");
            }
            currentDate = currentDate.plusDays(1);
        }
        List<String> list = new ArrayList<>();
        list.add(totalUserList.toString());
        list.add(newUserList.toString());

        return list;
    }


    /**
     * 获取营业额数据
     *
     * @param begin
     * @param end
     * @return
     */
    private String getTurnoverList(LocalDate begin, LocalDate end) {
        List<TurnoverStatistic> list = orderMapper.getDayAndAmountByDate(begin, end.plusDays(1));
        Map<LocalDate, BigDecimal> map = list.stream()
                .collect(Collectors.toMap(TurnoverStatistic::getDay, TurnoverStatistic::getAmount));

        StringBuilder turnoverList = new StringBuilder();
        LocalDate currentDate = begin;
        while (!currentDate.isAfter(end)) {
            BigDecimal amount = map.getOrDefault(currentDate, BigDecimal.ZERO);
            turnoverList.append(amount.setScale(2, RoundingMode.HALF_UP));
            if (!currentDate.equals(end)) {
                turnoverList.append(",");
            }
            currentDate = currentDate.plusDays(1);
        }

        return turnoverList.toString();
    }


    /**
     * 获取日期列表
     *
     * @return
     */
    private String getDateList(LocalDate begin, LocalDate end) {

        if (begin.isAfter(end)) {
            return null;
        }
        StringBuilder date = new StringBuilder();
        LocalDate currentDate = begin;
        while (!currentDate.isAfter(end)) {
            date.append(currentDate);
            if (!currentDate.equals(end)) {
                date.append(",");
            }
            currentDate = currentDate.plusDays(1);
        }
        return date.toString();
    }


}
